#include <ESP8266WiFi.h>

//巴法云服务器地址默认即可
#define TCP_SERVER_ADDR "bemfa.com"
//服务器端口//TCP创客云端口8344//TCP设备云端口8340
#define TCP_SERVER_PORT "8344"

///****************只需要修改的地方,有5个*****************///

//1.WIFI名称，可以用手机热点，区分大小写，不要写错
#define DEFAULT_STASSID  "TangH"
//2.WIFI密码
#define DEFAULT_STAPSW "20010228zxf"
//3.巴法云用户私钥，可在控制台获取,修改为自己的UID
String UID = "97526289e77c26379e50f859bf221184";
//4.主题名字，可在控制台新建
String TOPIC = "liym123";
//5.主题名字，可在控制台新建
String TOPIC2  = "wenn";  //用于控制的主题
const int LED_Pin = 0;  //LED引脚值，GPIO0引脚
const int FAN_Pin = 2;  //风扇引脚值，GPIO2引脚            
///*********************************************///
//led 控制函数
void turnOnLed();
void turnOffLed();

//风扇控制函数
void turnOnFan();
void turnOffFan();
//led状态
String my_led_status = "D_OFF";
//风扇状态
String my_fan_status = "F_OFF";
//宠物状态
String at_home = "H_YES";
//设置上传速率1s（1s<=upDataTime<=60s）
#define upDataTime 1*1000

//最大字节数
#define MAX_PACKETSIZE 512

      /*****************获取到的传感器数值*****************/
      //串口获得的数据,尝试使用char 发送 
      char Rxbuff[]  = "";//字符串函数
      char data1 =0;
      char data2 =0;
      char data3 =0;
      char data4 = 0;
      char data5 = 0;
      char data6 = 0;
      char data7 = 0;
      char data8 = 0;
      char data9 = 0;
      char data10 = 0;
      char data11 = 0;
      char data12 = 0;
      char data13 = 0;
      
//tcp客户端相关初始化，默认即可
WiFiClient TCPclient;
String TcpClient_Buff = "";
unsigned int TcpClient_BuffIndex = 0;
unsigned long TcpClient_preTick = 0;
unsigned long preHeartTick = 0;//心跳
unsigned long preTCPStartTick = 0;//连接
bool preTCPConnected = false;



//相关函数初始化
//连接WIFI
void doWiFiTick();
void startSTA();

//TCP初始化连接
void doTCPClientTick();
void startTCPClient();
void sendtoTCPServer(String p);

/*
  *发送数据到TCP服务器
 */
void sendtoTCPServer(String p){
  
  if (!TCPclient.connected()) 
  {
    Serial.println("Client is not readly");
    return;
  }
  TCPclient.print(p);
  Serial.println("[Send to TCPServer]:String");
  Serial.println(p);
}


/*
  *初始化和服务器建立连接
*/
void startTCPClient(){
  if(TCPclient.connect(TCP_SERVER_ADDR, atoi(TCP_SERVER_PORT))){
    Serial.print("\nConnected to server:");
    Serial.printf("%s:%d\r\n",TCP_SERVER_ADDR,atoi(TCP_SERVER_PORT));
	
	String tcpTemp="";
    tcpTemp = "cmd=1&uid="+UID+"&topic="+TOPIC2+"\r\n";
	
	sendtoTCPServer(tcpTemp);
    preTCPConnected = true;
    preHeartTick = millis();
    TCPclient.setNoDelay(true);
  }
  else{
    Serial.print("Failed connected to server:");
    Serial.println(TCP_SERVER_ADDR);
    TCPclient.stop();
    preTCPConnected = false;
  }
  preTCPStartTick = millis();
}


/*
  *检查数据，发送数据
*/
void doTCPClientTick(){
 //检查是否断开，断开后重连
   if(WiFi.status() != WL_CONNECTED) return;

  if (!TCPclient.connected()) {//断开重连

  if(preTCPConnected == true){

    preTCPConnected = false;
    preTCPStartTick = millis();
    Serial.println();
    Serial.println("TCP Client disconnected.");
    TCPclient.stop();
  }
  else if(millis() - preTCPStartTick > 1*1000)//重新连接
    startTCPClient();
  }
  else
  {
    if (TCPclient.available()) {//收数据
      char c =TCPclient.read();
      TcpClient_Buff +=c;
      TcpClient_BuffIndex++;
      TcpClient_preTick = millis();
      
      if(TcpClient_BuffIndex>=MAX_PACKETSIZE - 1){
        TcpClient_BuffIndex = MAX_PACKETSIZE-2;
        TcpClient_preTick = TcpClient_preTick - 200;
      }
      preHeartTick = millis();
    }
    if(millis() - preHeartTick >= upDataTime){//上传数据
      preHeartTick = millis();
      /*********************数据上传*******************/
                  //为避免干扰发送数据到wifi模块, 1温度，2湿度，3.报警标志位 4.目标重量设定值,+5.灯状态+6.风扇状态+7.光照强度，8.实物重量
      String upstr = "";
      upstr = "cmd=2&uid="+UID+"&topic="+TOPIC+"&msg=#"+data1+data2+"#"+data3+data4+"#"+data5+"#"
    +data6+data7+data8+"#"+data9+data10+"#"+my_led_status+"#"+my_fan_status+"#"+data11+data12+data13+"#\r\n";
      sendtoTCPServer(upstr);
      upstr = "";
    }
  }
  if((TcpClient_Buff.length() >= 1) && (millis() - TcpClient_preTick>=200))
  {//data ready
    TCPclient.flush();
    Serial.println("Buff");
    Serial.println(TcpClient_Buff);

if((TcpClient_Buff.indexOf("&msg=11") > 0)) {
      turnOnLed();
    //////字符串匹配，检测发了的字符串TcpClient_Buff里面是否包含&msg=off，如果有，则关闭开关
    }else if((TcpClient_Buff.indexOf("&msg=10") > 0)) {
      turnOffLed();
    }
	
	if((TcpClient_Buff.indexOf("&msg=21") > 0)) {
      turnOnFan();
    //////字符串匹配，检测发了的字符串TcpClient_Buff里面是否包含&msg=21，如果有，则关闭开关
    }else if((TcpClient_Buff.indexOf("&msg=20") > 0)) {
      turnOffFan();
    }

   TcpClient_Buff="";
   TcpClient_BuffIndex = 0;
  }
}

//打开灯泡
void turnOnLed(){

  digitalWrite(LED_Pin,LOW); //低电平打开LED
  my_led_status = "D_ON";
}
//关闭灯泡
void turnOffLed(){

  digitalWrite(LED_Pin,HIGH);
  my_led_status = "D_OFF";
}

//打开风扇
void turnOnFan(){

  digitalWrite(FAN_Pin,HIGH);//高电平打开继电器
  my_fan_status = "F_ON";
}
//关闭风扇
void turnOffFan(){

  digitalWrite(FAN_Pin,LOW);
  my_fan_status = "F_OFF";
}

void startSTA(){
  WiFi.disconnect();
  WiFi.mode(WIFI_STA);
  WiFi.begin(DEFAULT_STASSID, DEFAULT_STAPSW);

}

/**************************************************************************
                                 WIFI  
***************************************************************************/
/*
  WiFiTick
  检查是否需要初始化WiFi
  检查WiFi是否连接上，若连接成功启动TCP Client
  控制指示灯
*/
void doWiFiTick(){
  static bool startSTAFlag = false;
  static bool taskStarted = false;
  static uint32_t lastWiFiCheckTick = 0;

  if (!startSTAFlag) {
    startSTAFlag = true;
    startSTA();
    Serial.printf("Heap size:%d\r\n", ESP.getFreeHeap());
  }

  //未连接1s重连
  if ( WiFi.status() != WL_CONNECTED ) {
    if (millis() - lastWiFiCheckTick > 1000) {
      lastWiFiCheckTick = millis();
    }
  }
  //连接成功建立
  else {
    if (taskStarted == false) {
      taskStarted = true;
      Serial.print("\r\nGet IP Address: ");
      Serial.println(WiFi.localIP());
      startTCPClient();
    }
  }
}

// 初始化，相当于main 函数
void setup() {
  Serial.begin(115200);
  
  //初始化引脚为输出
	pinMode(LED_Pin,OUTPUT);
	  //初始化引脚为输出
	pinMode(FAN_Pin,OUTPUT);
  
   digitalWrite(LED_Pin,HIGH);
   digitalWrite(FAN_Pin,LOW);
}

//循环
void loop() 
{
   if(Serial.available())
  {
  doWiFiTick();
  doTCPClientTick();

   String Rxbuff = "";//缓存清零
  while (Serial.available() > 0)//循环串口是否有数据
      {
        Rxbuff += char(Serial.read());   //叠加数据到comdata
        delay(2); //延时2ms
      } 
      int t;
      //发送数据到wifi模块,  1温度，2湿度，3.报警标志位 4.目标重量设定值,5.光照强度，6.实物重量
      for (t=0;t<Rxbuff.length() ;t++)
      {
       data1 =Rxbuff[0];//温度
       data2 =Rxbuff[1];
       
       data3 =Rxbuff[2];//湿度
       data4 =Rxbuff[3];
       
       data5 =Rxbuff[4];//报警标志位
     
       data6 =Rxbuff[5];//目标重量设定值
       data7 =Rxbuff[6];
       data8 =Rxbuff[7];
       
       data9 =Rxbuff[8];//光照强度
       data10 =Rxbuff[9];
       
       data11 =Rxbuff[10];//实物重量
       data12 =Rxbuff[11];
       data13 =Rxbuff[12];
       
//       if(data5==1)  //不报警，在家
//    {
//    at_home = "H_YES"; 
//    }
//    else 
//    {
//     at_home = "H_NO"; 
//      }
        
    }
   }
}
